#include <schedule.h>
#include <8259A.h>
#include <task.h>
#include <desc.h>
#include <share.h>
#include <queue.h>

/******************************************************************************
* 函数名称: static void Free2Ready(void)
* 功能说明: 将空闲任务队列中的任务节点迁移到就绪任务队列中
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static void Free2Ready(void)
{
    QUEUE_NODE* node = NULL;
    // 当空闲任务队列不为空 且 就绪任务队列长度 < 就绪任务队列最大长度
    while((QueueLength(&TASK_FREE_QUEUE) > 0) && (QueueLength(&TASK_READY_QUEUE) < MAX_READY_TASK))
    {
        // 取空闲任务队列中一个任务节点
        node = QueueRemove(&TASK_FREE_QUEUE);
        // 放到就绪任务队列中
        QueueAdd(&TASK_READY_QUEUE, node);
    }
}

/******************************************************************************
* 函数名称: static void Ready2Running(void)
* 功能说明: 将就绪任务队列中的任务节点迁移到执行任务队列中
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
static void Ready2Running(void)
{
    QUEUE_NODE* node = NULL;
    // 当就绪任务队列不为空 且 执行任务队列长度 < 执行任务队列最大长度
    while((QueueLength(&TASK_READY_QUEUE) > 0) && (QueueLength(&TASK_RUNNING_QUEUE) < MAX_RUNNING_TASK))
    {
        // 取就绪任务队列中一个任务节点
        node = QueueRemove(&TASK_READY_QUEUE);
        // 放到执行任务队列中
        QueueAdd(&TASK_RUNNING_QUEUE, node);
    }
}

/******************************************************************************
* 函数名称: void schedule(void)
* 功能说明: 进程调度
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void schedule(void)
{
    QUEUE_NODE* node = NULL;

    Free2Ready();       // 将空闲任务队列中的任务节点迁移到就绪任务队列中
    Ready2Running();    // 将就绪任务队列中的任务节点迁移到执行任务队列中

    // 从执行任务队列中取出一个任务节点并执行该任务，再将该任务节点重新添加到执行任务队列中
    node = QueueRemove(&TASK_RUNNING_QUEUE);
    current_task = (volatile TASK *)((TASK_QUEUE_NODE *)QUEUE_NODE(node, TASK_QUEUE_NODE, QueueNode)->task);
    QueueAdd(&TASK_RUNNING_QUEUE, node);

    TSS* tss = (TSS*)(*(U32*)TSS_ENTRY_ADDR);                             // 找到 TSS
    tss->esp0 = (U32)(&current_task->reg) + sizeof(current_task->reg);    // TSS.esp0 指向任务上下文数据结构 reg 的末尾
    current_reg = (U32)(&current_task->reg);                              // current_reg 指向任务上下文数据结构 reg 的起始位置
}

/******************************************************************************
* 函数名称: void Int0x20Handle(void)
* 功能说明: 0x20 号中断中断服务程序的逻辑功能部分
* 输入参数: 无
* 输出参数: 无
* 函数返回: 无
* 其它说明: 无
******************************************************************************/
void Int0x20Handle(void)
{
    static U32 count = 0;

    if(count++ % 5 == 4)
    {
        schedule();
    }
    write_m_EOI();  
}

